{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Title: #Building H2O"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Difficulty: #Medium"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Category Title: #Concurrency"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tag Slug: #concurrency"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Name Translated: #多线程"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solution Name: H2O"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Title: #H2O 生成"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Content:\n",
    "<p>现在有两种线程，氧 <code>oxygen</code> 和氢 <code>hydrogen</code>，你的目标是组织这两种线程来产生水分子。</p>\n",
    "\n",
    "<p>存在一个屏障（barrier）使得每个线程必须等候直到一个完整水分子能够被产生出来。</p>\n",
    "\n",
    "<p>氢和氧线程会被分别给予 <code>releaseHydrogen</code> 和 <code>releaseOxygen</code> 方法来允许它们突破屏障。</p>\n",
    "\n",
    "<p>这些线程应该三三成组突破屏障并能立即组合产生一个水分子。</p>\n",
    "\n",
    "<p>你必须保证产生一个水分子所需线程的结合必须发生在下一个水分子产生之前。</p>\n",
    "\n",
    "<p>换句话说:</p>\n",
    "\n",
    "<ul>\n",
    "\t<li>如果一个氧线程到达屏障时没有氢线程到达，它必须等候直到两个氢线程到达。</li>\n",
    "\t<li>如果一个氢线程到达屏障时没有其它线程到达，它必须等候直到一个氧线程和另一个氢线程到达。</li>\n",
    "</ul>\n",
    "\n",
    "<p>书写满足这些限制条件的氢、氧线程同步代码。</p>\n",
    "\n",
    "<p>&nbsp;</p>\n",
    "\n",
    "<p><strong>示例 1:</strong></p>\n",
    "\n",
    "<pre>\n",
    "<strong>输入: </strong>water = \"HOH\"\n",
    "<strong>输出: </strong>\"HHO\"\n",
    "<strong>解释:</strong> \"HOH\" 和 \"OHH\" 依然都是有效解。\n",
    "</pre>\n",
    "\n",
    "<p><strong>示例 2:</strong></p>\n",
    "\n",
    "<pre>\n",
    "<strong>输入: </strong>water = \"OOHHHH\"\n",
    "<strong>输出: </strong>\"HHOHHO\"\n",
    "<strong>解释:</strong> \"HOHHHO\", \"OHHHHO\", \"HHOHOH\", \"HOHHOH\", \"OHHHOH\", \"HHOOHH\", \"HOHOHH\" 和 \"OHHOHH\" 依然都是有效解。\n",
    "</pre>\n",
    "\n",
    "<p>&nbsp;</p>\n",
    "\n",
    "<p><strong>提示：</strong></p>\n",
    "\n",
    "<ul>\n",
    "\t<li><code>3 * n == water.length</code></li>\n",
    "\t<li><code>1 &lt;= n &lt;= 20</code></li>\n",
    "\t<li><code>water[i] == 'O' or 'H'</code></li>\n",
    "\t<li>输入字符串&nbsp;<code>water</code>&nbsp;中的 <font color=\"#c7254e\"><font face=\"Menlo, Monaco, Consolas, Courier New, monospace\"><span style=\"font-size:12.6px\"><span style=\"background-color:#f9f2f4\">'H'</span></span></font></font>&nbsp;总数将会是 <code>2 * n</code> 。</li>\n",
    "\t<li>输入字符串&nbsp;<code>water</code>&nbsp;中的 <font color=\"#c7254e\"><font face=\"Menlo, Monaco, Consolas, Courier New, monospace\"><span style=\"font-size:12.6px\"><span style=\"background-color:#f9f2f4\">'O'</span></span></font></font>&nbsp;总数将会是 <code>n</code> 。</li>\n",
    "</ul>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Description: [building-h2o](https://leetcode.cn/problems/building-h2o/description/)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solutions: [building-h2o](https://leetcode.cn/problems/building-h2o/solutions/)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_cases = ['\"HOH\"', '\"OOHHHH\"']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.h, self.o = [], []\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.h.append(releaseHydrogen)\n",
    "        self.res()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.o.append(releaseOxygen)\n",
    "        self.res()\n",
    "        \n",
    "    def res(self):\n",
    "        if len(self.h) > 1 and len(self.o) > 0:\n",
    "            self.h.pop(0)()\n",
    "            self.h.pop(0)()\n",
    "            self.o.pop(0)()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Lock\n",
    "\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.oLock = Lock()\n",
    "        self.haLock = Lock()\n",
    "        self.hbLock = Lock()\n",
    "        self.oLock.acquire()\n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        if self.haLock.locked():\n",
    "            self.hbLock.acquire()\n",
    "            releaseHydrogen()\n",
    "        else:\n",
    "            self.haLock.acquire()\n",
    "            releaseHydrogen()\n",
    "        if self.haLock.locked() and self.hbLock.locked():\n",
    "            self.oLock.release()\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        self.oLock.acquire()\n",
    "        releaseOxygen()\n",
    "        self.haLock.release()\n",
    "        self.hbLock.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semah= threading.Semaphore(2)\n",
    "        self.semao = threading.Semaphore(1)\n",
    "        self.produce = threading.Event()\n",
    "        self.produce.clear()\n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        self.semah.acquire()\n",
    "        releaseHydrogen()\n",
    "        if self.produce.isSet():\n",
    "            self.semao.release()\n",
    "        self.produce.set()\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        self.semao.acquire()\n",
    "        releaseOxygen()\n",
    "        if self.produce.isSet():\n",
    "            self.semah.release()\n",
    "            self.semah.release()\n",
    "        self.produce.clear()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semH = Semaphore(2)\n",
    "        self.semO = Semaphore(1)\n",
    "        self.semO.acquire()\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.semH.acquire()\n",
    "        releaseHydrogen()\n",
    "        if self.semH._value == 0:\n",
    "            self.semO.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.semO.acquire()\n",
    "        releaseOxygen()\n",
    "        self.semH.release()\n",
    "        self.semH.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semH = Semaphore(2)\n",
    "        self.semO = Semaphore(1)\n",
    "        self.semO.acquire()\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.semH.acquire()\n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        releaseHydrogen()\n",
    "        if self.semH._value == 0:\n",
    "            self.semO.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.semO.acquire()\n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        releaseOxygen()\n",
    "        self.semH.release()\n",
    "        self.semH.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore, Lock\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.sema_H = Semaphore(2)\n",
    "        self.sema_O = Semaphore(1)\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.sema_H.acquire()        \n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        releaseHydrogen()\n",
    "        if self.sema_H._value == 0 and self.sema_O._value == 0:\n",
    "            self.sema_H.release()\n",
    "            self.sema_H.release()\n",
    "            self.sema_O.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.sema_O.acquire()        \n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        releaseOxygen()\n",
    "        if self.sema_H._value == 0 and self.sema_O._value == 0:\n",
    "            self.sema_H.release()\n",
    "            self.sema_H.release()\n",
    "            self.sema_O.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore, Lock\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.sema_H = Semaphore(2)\n",
    "        self.sema_O = Semaphore(1)\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.sema_H.acquire()        \n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        releaseHydrogen()\n",
    "        if self.sema_H._value == 0 and self.sema_O._value == 0:\n",
    "            self.sema_H.release()\n",
    "            self.sema_H.release()\n",
    "            self.sema_O.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.sema_O.acquire()        \n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        releaseOxygen()\n",
    "        if self.sema_H._value == 0 and self.sema_O._value == 0:\n",
    "            self.sema_H.release()\n",
    "            self.sema_H.release()\n",
    "            self.sema_O.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.h,self.o=[],[]\n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        self.h.append(releaseHydrogen)\n",
    "        self.res()\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        self.o.append(releaseOxygen)\n",
    "        self.res()\n",
    "\n",
    "    def res(self):\n",
    "        if len(self.h)>1 and len(self.o)>0:\n",
    "            self.h.pop(0)() # 将最右边的函数弹出来，并且执行它\n",
    "            self.h.pop(0)()\n",
    "            self.o.pop(0)()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        # pass\n",
    "        self.semo = Semaphore() # o起始可打印次数1\n",
    "        self.semh = Semaphore(2) # h起始可打印次数2\n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.semh.acquire()\n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        releaseHydrogen()\n",
    "        if(self.semh._value == 0):\n",
    "            self.semo.release()\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.semo.acquire()\n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        releaseOxygen()\n",
    "        self.semh.release(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Semaphore, Lock, Event\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaH = Semaphore(2)\n",
    "        self.semaO = Semaphore(1)\n",
    "        self.event = Event()\n",
    "        self.event.clear()\n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        self.semaH.acquire()\n",
    "        releaseHydrogen()\n",
    "\n",
    "        if self.event.is_set():\n",
    "            self.semaO.release()\n",
    "        self.event.set()\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        self.semaO.acquire()\n",
    "        releaseOxygen()\n",
    "        if self.event.is_set():\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "\n",
    "        self.event.clear()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Semaphore, Lock, Event\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaH = Semaphore(2)\n",
    "        self.semaO = Semaphore(0)\n",
    "        self.count = 0 \n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        self.semaH.acquire()\n",
    "        releaseHydrogen()\n",
    "        self.count += 1 \n",
    "        if self.count == 2:\n",
    "            self.semaO.release()\n",
    "            self.count = 0 \n",
    "     \n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        self.semaO.acquire()\n",
    "        releaseOxygen()\n",
    "        self.semaH.release()\n",
    "        self.semaH.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Semaphore, Lock, Event\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaH = Semaphore(2)\n",
    "        self.semaO = Semaphore(0)\n",
    "        self.count = 0 \n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        self.semaH.acquire()\n",
    "        releaseHydrogen()\n",
    "        self.count += 1 \n",
    "        if self.count == 2:\n",
    "            self.semaO.release()\n",
    "            self.count = 0 \n",
    "     \n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        self.semaO.acquire()\n",
    "        releaseOxygen()\n",
    "        self.semaH.release()\n",
    "        self.semaH.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Lock, Semaphore\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semah= threading.Semaphore(2)\n",
    "        self.semao = threading.Semaphore(1)\n",
    "        self.produce = threading.Event()\n",
    "        self.produce.clear()\n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        self.semah.acquire()\n",
    "        releaseHydrogen()\n",
    "        if self.produce.isSet():\n",
    "            self.semao.release()\n",
    "        self.produce.set()\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        self.semao.acquire()\n",
    "        releaseOxygen()\n",
    "        if self.produce.isSet():\n",
    "            self.semah.release()\n",
    "            self.semah.release()\n",
    "        self.produce.clear()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.s1 = threading.Semaphore(2)\n",
    "        self.s2 = threading.Semaphore(1)\n",
    "        self.s2.acquire()\n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.s1.acquire()\n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        releaseHydrogen()\n",
    "        if self.s1._value == 0:\n",
    "            self.s2.release()\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.s2.acquire()\n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        releaseOxygen()\n",
    "        self.s1.release()\n",
    "        self.s1.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore, Lock\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaH = Semaphore(2)\n",
    "        self.semaO = Semaphore(1)\n",
    "        self.lock = Lock()\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.semaH.acquire()\n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        releaseHydrogen()\n",
    "        self.generateH2O()\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.semaO.acquire()\n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        releaseOxygen()\n",
    "        self.generateH2O()\n",
    "\n",
    "    def generateH2O(self) -> None:\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import * \n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.oxygenSem = Semaphore(1)\n",
    "        self.hydrogenSem = Semaphore(2)\n",
    "        self.lock = Lock()\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.hydrogenSem.acquire(1)\n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        releaseHydrogen()\n",
    "        self.lock.acquire()\n",
    "        if self.hydrogenSem._value == 0 and self.oxygenSem._value == 0:\n",
    "            self.hydrogenSem.release(2)\n",
    "            self.oxygenSem.release(1)\n",
    "        self.lock.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.oxygenSem.acquire()\n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        releaseOxygen()\n",
    "        self.lock.acquire()\n",
    "        if self.hydrogenSem._value == 0 and self.oxygenSem._value == 0:\n",
    "            self.hydrogenSem.release(2)\n",
    "            self.oxygenSem.release(1)\n",
    "        self.lock.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "class H2O(object):\n",
    "    def __init__(self):\n",
    "        self.O=threading.Semaphore(1)\n",
    "        self.H=threading.Semaphore(2)\n",
    "        self.Ol = threading.Lock()\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen):\n",
    "        \"\"\"\n",
    "        :type releaseHydrogen: method\n",
    "        :rtype: void\n",
    "        \"\"\"\n",
    "        \n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        self.H.acquire()\n",
    "        releaseHydrogen()\n",
    "        \n",
    "        with self.Ol:\n",
    "            if self.H._value == 0:\n",
    "                self.O.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen):\n",
    "        \"\"\"\n",
    "        :type releaseOxygen: method\n",
    "        :rtype: void\n",
    "        \"\"\"\n",
    "        \n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        self.O.acquire()\n",
    "        releaseOxygen()\n",
    "        self.H.release()\n",
    "        self.H.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semah= threading.Semaphore(2)\n",
    "        self.semao = threading.Semaphore(1)\n",
    "        self.produce = threading.Event()\n",
    "        self.produce.clear()\n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        self.semah.acquire()\n",
    "        releaseHydrogen()\n",
    "        if self.produce.isSet():\n",
    "            self.semao.release()\n",
    "        self.produce.set()\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        self.semao.acquire()\n",
    "        releaseOxygen()\n",
    "        if self.produce.isSet():\n",
    "            self.semah.release()\n",
    "            self.semah.release()\n",
    "        self.produce.clear()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Condition, Lock\n",
    "from typing import Callable\n",
    "\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.g = Lock()\n",
    "        self.o = Condition(self.g)\n",
    "        self.h = Condition(self.g)\n",
    "        self.hn = 0\n",
    "        self.on = 0\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        with self.g:\n",
    "            self.h.wait_for(lambda: self.hn < 2)\n",
    "            releaseHydrogen()\n",
    "            self.hn += 1\n",
    "            self.on -= 0.5\n",
    "            self.o.notify()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        with self.g:\n",
    "            self.o.wait_for(lambda: self.on <= 0)\n",
    "            releaseOxygen()\n",
    "            self.on += 1\n",
    "            self.hn -= 2\n",
    "            self.h.notify(2)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore, Lock\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaH = Semaphore(2)\n",
    "        self.semaO = Semaphore(1)\n",
    "        self.lock = Lock()\n",
    "        pass\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.semaH.acquire()\n",
    "        releaseHydrogen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.semaO.acquire()\n",
    "        releaseOxygen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "            self.semaO.release()\n",
    "        self.lock.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "H2O生成\n",
    "\"\"\"\n",
    "from typing import Callable\n",
    "import threading\n",
    "\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.H = threading.Semaphore(2)\n",
    "        self.O = threading.Semaphore(1)\n",
    "        self.H2O_b = threading.Barrier(3)\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        self.H.acquire()\n",
    "        releaseHydrogen()\n",
    "        self.H2O_b.wait()\n",
    "        self.H.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        self.O.acquire()\n",
    "        releaseOxygen()\n",
    "        self.H2O_b.wait()\n",
    "        self.O.release()\n",
    "\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "\n",
    "    def releaseHydrogen():\n",
    "        print(\"H\", end=\"\")\n",
    "\n",
    "    def releaseOxygen():\n",
    "        print(\"O\", end=\"\")\n",
    "\n",
    "    W = H2O()\n",
    "    water = \"OOHHHHHOHHHO\"\n",
    "    print(water)\n",
    "    A = []\n",
    "    for atom in water:\n",
    "        if atom == \"O\":\n",
    "            A.append(threading.Thread(target=W.oxygen, args=(releaseOxygen, )))\n",
    "        else:\n",
    "            A.append(\n",
    "                threading.Thread(target=W.hydrogen, args=(releaseHydrogen, )))\n",
    "\n",
    "    for a in A:\n",
    "        a.start()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore, Lock\n",
    "from typing import Callable\n",
    "\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaH = Semaphore(2)\n",
    "        self.semaO = Semaphore(1)\n",
    "        self.lock = Lock()\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: Callable[[], None]) -> None:\n",
    "        self.semaH.acquire()\n",
    "        releaseHydrogen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release(2)\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: Callable[[], None]) -> None:\n",
    "        self.semaO.acquire()\n",
    "        releaseOxygen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release(2)\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore, Lock\n",
    "from typing import Callable\n",
    "\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaH = Semaphore(2)\n",
    "        self.semaO = Semaphore(1)\n",
    "        self.lock = Lock()\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: Callable[[], None]) -> None:\n",
    "        self.semaH.acquire()\n",
    "        releaseHydrogen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release(2)\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: Callable[[], None]) -> None:\n",
    "        self.semaO.acquire()\n",
    "        releaseOxygen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release(2)\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Lock, Semaphore\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaH = Semaphore(2)\n",
    "        self.semaO = Semaphore(1)\n",
    "        self.lock = Lock()       \n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.semaH.acquire()\n",
    "        releaseHydrogen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.semaO.acquire()\n",
    "        releaseOxygen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "            self.semaO.release()\n",
    "        self.lock.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Lock, Condition\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.st = 0\n",
    "        self.lck = Lock()\n",
    "        self.cv = Condition(self.lck)\n",
    "\n",
    "    def transfer(self, ele: int) -> None:\n",
    "        match self.st:\n",
    "            case 0:\n",
    "                self.st = 1 if ele == 0 else 2\n",
    "            case 1:\n",
    "                self.st = 5 if ele == 0 else 3\n",
    "            case 2:\n",
    "                self.st = 4\n",
    "            case _:\n",
    "                self.st = 0\n",
    "        self.cv.notify_all()\n",
    "        self.cv.release()\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        self.cv.acquire()\n",
    "        self.cv.wait_for(lambda: self.st != 5)\n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        releaseHydrogen()\n",
    "        self.transfer(0)\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        self.cv.acquire()\n",
    "        self.cv.wait_for(lambda: self.st < 2 or self.st == 5)\n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        releaseOxygen()\n",
    "        self.transfer(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore, Lock\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaH = Semaphore(2)\n",
    "        self.semaO = Semaphore(1)\n",
    "        self.lock = Lock()\n",
    "        pass\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.semaH.acquire()\n",
    "        releaseHydrogen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.semaO.acquire()\n",
    "        releaseOxygen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading\n",
    "from threading import Semaphore, Lock, Event\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaH = Semaphore(2)\n",
    "        self.semaO = Semaphore(1)\n",
    "        self.count = 0 \n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        self.semaH.acquire()\n",
    "        releaseHydrogen()\n",
    "        self.count += 1 \n",
    "        if self.count == 2:\n",
    "            self.semaO.release()\n",
    "            self.count = 0 \n",
    "     \n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        \n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        self.semaO.acquire()\n",
    "        releaseOxygen()\n",
    "        self.semaH.release()\n",
    "        self.semaH.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore, Lock\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        # Initially 2 hydrogens can proceed, 0 oxygen can proceed\n",
    "        self.h_sema = Semaphore(2)\n",
    "        self.o_sema = Semaphore(0)\n",
    "        self.h_count = 0\n",
    "        self.lock = Lock()\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.h_sema.acquire()\n",
    "        with self.lock:\n",
    "            # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "            releaseHydrogen()\n",
    "            self.h_count += 1\n",
    "            if self.h_count == 2: # When we have 2 hydrogens, release an oxygen\n",
    "                self.o_sema.release()\n",
    "                self.h_count = 0\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.o_sema.acquire()\n",
    "        with self.lock:\n",
    "            # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "            releaseOxygen()\n",
    "            # Now we can release 2 hydrogens for the next molecule\n",
    "            self.h_sema.release()\n",
    "            self.h_sema.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from queue import Queue\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        # here we has two threads\n",
    "        self._que_h = Queue(2)\n",
    "        self._que_o = Queue(1)\n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self._que_h.put('H')\n",
    "\n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        releaseHydrogen()\n",
    "\n",
    "        if self._que_h.full() and self._que_o.full():\n",
    "            self._que_h.get()\n",
    "            self._que_h.get()\n",
    "            self._que_o.get()\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self._que_o.put('O')\n",
    "\n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        releaseOxygen()\n",
    "        \n",
    "        if self._que_h.full() and self._que_o.full():\n",
    "            self._que_h.get()\n",
    "            self._que_h.get()\n",
    "            self._que_o.get()\n",
    "\n",
    "\n",
    "# 'H'队列maxsize设置成2，'O'队列maxsize设置成1，这样单个队列满了的时候，该线程处于wait状态 否则队列一直不满的线程继续工作，直到两个队列都满了，则执行pop操作，即完成一次H2O的弹出\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore, Lock\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaH = Semaphore(2)\n",
    "        self.semaO = Semaphore(1)\n",
    "        self.lock = Lock()\n",
    "        pass\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.semaH.acquire()\n",
    "        releaseHydrogen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.semaO.acquire()\n",
    "        releaseOxygen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from queue import Queue\n",
    "\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.hydrogen_queue = Queue(2)\n",
    "        self.oxygen_queue = Queue(1)\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        self.hydrogen_queue.put(1)\n",
    "        releaseHydrogen()\n",
    "        self.clean()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        self.oxygen_queue.put(1)\n",
    "        releaseOxygen()\n",
    "        self.clean()\n",
    "    def clean(self):\n",
    "        if self.hydrogen_queue.full() and self.oxygen_queue.full():\n",
    "            self.hydrogen_queue.get()\n",
    "            self.hydrogen_queue.get()\n",
    "            self.oxygen_queue.get()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import threading \n",
    "import time \n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaphore=threading.Semaphore(2)\n",
    "        self.semaphore1=threading.Semaphore(1)\n",
    "        self.bar=threading.Barrier(3)\n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.semaphore.acquire()\n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        releaseHydrogen()\n",
    "        self.bar.wait()\n",
    "        self.semaphore.release()\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.semaphore1.acquire()\n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        releaseOxygen()\n",
    "        self.bar.wait()\n",
    "        self.semaphore1.release()\n",
    "        #self.semaphore.release()\n",
    "\n",
    "if __name__=='__main__':\n",
    "    w=H2O()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from queue import Queue\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        # here we has two threads\n",
    "        self._que_h = Queue(2)\n",
    "        self._que_o = Queue(1)\n",
    "\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self._que_h.put('H')\n",
    "\n",
    "        # releaseHydrogen() outputs \"H\". Do not change or remove this line.\n",
    "        releaseHydrogen()\n",
    "\n",
    "        if self._que_h.full() and self._que_o.full():\n",
    "            self._que_h.get()\n",
    "            self._que_h.get()\n",
    "            self._que_o.get()\n",
    "\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self._que_o.put('O')\n",
    "\n",
    "        # releaseOxygen() outputs \"O\". Do not change or remove this line.\n",
    "        releaseOxygen()\n",
    "        \n",
    "        if self._que_h.full() and self._que_o.full():\n",
    "            self._que_h.get()\n",
    "            self._que_h.get()\n",
    "            self._que_o.get()\n",
    "\n",
    "\n",
    "# 'H'队列maxsize设置成2，'O'队列maxsize设置成1，这样单个队列满了的时候，该线程处于wait状态 否则队列一直不满的线程继续工作，直到两个队列都满了，则执行pop操作，即完成一次H2O的弹出\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore, Lock\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaH = Semaphore(2)\n",
    "        self.semaO = Semaphore(1)\n",
    "        self.lock = Lock()\n",
    "        pass\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.semaH.acquire()\n",
    "        releaseHydrogen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.semaO.acquire()\n",
    "        releaseOxygen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from threading import Semaphore, Lock\n",
    "\n",
    "class H2O:\n",
    "    def __init__(self):\n",
    "        self.semaH = Semaphore(2)\n",
    "        self.semaO = Semaphore(1)\n",
    "        self.lock = Lock()\n",
    "        pass\n",
    "\n",
    "    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:\n",
    "        self.semaH.acquire()\n",
    "        releaseHydrogen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "            self.semaO.release()\n",
    "        self.lock.release()\n",
    "\n",
    "    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:\n",
    "        self.semaO.acquire()\n",
    "        releaseOxygen()\n",
    "        self.lock.acquire()\n",
    "        if self.semaH._value == 0 and self.semaO._value == 0:\n",
    "            self.semaH.release()\n",
    "            self.semaH.release()\n",
    "            self.semaO.release()\n",
    "        self.lock.release()"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 2
}
